from django.shortcuts import render

# Create your views here.
import random
import re
import string
from django.utils import timezone
import jwt
from django.contrib.auth.hashers import check_password, make_password
from rest_framework_jwt.utils import jwt_encode_handler
from user.tasks import send_code
from takeout import celery
import redis
from captcha.image import ImageCaptcha
from django.http import HttpResponse
from rest_framework.response import Response
from rest_framework.views import APIView
from user.models import UsersModel


# 效验用户名
class CheckUserNameView(APIView):
    def get(self,request,username):
        # 获取前端传来的用户名
        # 判断用户名格式

        if not username:
            return Response({'msg':'用户名不正确','code':400})
        # 判断用户名长度是否符合
        if not (2<= len(username)<=32):
            return Response({'msg':'用户名长度不符','code':400})
        try:
            # 用户名没有问题，就查数据库有没有该用户名
            user_count = UsersModel.objects.filter(username=username).count()
            if user_count:
                return Response({'msg': '用户已存在,请登录', 'code': 200})
        except Exception as e:
            print(e)

        # 此时说明用户名不存在，正常返回
        return Response({'msg': '用户不存在，请注册', 'code': 201})


# 校验手机号
class CheckMobile(APIView):
    def get(self,request,mobile):
        # 校验手机号格式
        rule = re.findall(r"^1[3-9]\d{9}$",mobile)
        if not rule:
            return Response({'msg':'手机号格式不正确','code':400})
        try:
            UsersModel.objects.get(mobile=mobile)
            # 此时获取到用户,说明此手机号已经存在，抛出错误
            return Response({'msg':'手机号已存在','code':400})
        except Exception as e:
            # 此时说明此手机号不存在，正常返回
            return Response({'msg':'ok','code':200})


# 生成图片验证码
class GenerateImgCode(APIView):
    # 生成图片验证码
    def get(self,request,uuid):
        # 如何生成图片验证码
        # 使用random模块和captzha模块
        # 生成随机字符串
        # string.ascii_letters: 所有字母的字符串（大小写）
        # string.digits： 所有的数字字符串（0-9）
        # random.sample： 随机采集指定位数的字符
        code = ''.join(random.sample(string.ascii_letters + string.digits, 4))
        # 把生成的随机数写到图片上
        img = ImageCaptcha()
        img_code = img.generate(code)# 生成图片是bytes 字节流
        print('生成的图片验证码是>>>',img_code)

        # #会把生成的图片验证码写入到redis中
        rds = redis.Redis(host='127.0.0.1',port=6379,db=0,password='123456')
        # #把图片验证码写入到redis
        # #key 是图片验证码的id 值是生成的随机数，有效期是60s
        rds.setex(str(uuid),60 * 3,code)
        print(code)
        rds.close() # 关闭 redis链接


        #  返回前端数据，是否指定数据格式
        return HttpResponse(img_code,content_type='image/png')


# 校验验证码
class CheckImageCode(APIView):
    def get(self,request):
        #1. 接收前端发送的参数，imageCodeID & imageCode
        uuid_ = request.query_params.get("imageCodeID")
        image_code_ = request.query_params.get("imageCode")
        # 2. 取出redis中的 图片验证码
        #     如果取不到，说明过期，响应204
        #     如果取到验证码，进行对比，注意： 统一大小写
        rds = redis.Redis(host='127.0.0.1',port=6379,db=0,password='123456')
        image_code = rds.get(uuid_)


        if not image_code:
            return Response({'code':204,'msg':'验证码过期'})

        # 3.
        # 根据对比结果，返回响应
        if image_code.decode().lower() == image_code_.lower():
            return Response({'code':200,'msg':'ok'})
        else:
            return Response({'code':204,'msg':'验证码错误'})


# 发送短信验证码
class SendSMSCode(APIView):
    def get(self, request):
        mobile = request.query_params.get('mobile')
        # 生成短信验证码
        data = random.randint(000000, 999999)
        if mobile:
            # 使用delay触发任务,会把短信验证码发送的结果存放到redis中
            resp = send_code.delay(mobile, code=data)
            print("异步发送短信验证码>>>", resp)
            if resp:
                rdc = redis.Redis(password='123456',host='localhost',port=6379)
                # 把短信验证码写入redis
                rdc.setex("sms_%s" % mobile, 600, data)
                return Response({'msg':data,'code': 200,})
            else:
                return Response({'msg': "发送失败", "code": 500})
        else:
            return Response({'msg': "参数错误", "code": 400})


# 校验注册信息
class RegisterView(APIView):
    def post(self,request):
        # 前端传入 userName, pwd, mobile, agree
        username = request.data.get("username")
        password = request.data.get("password")
        mobile = request.data.get("mobile")
        sms_code = request.data.get("sms_code")
        # 判断短信验证码是否正确
        rdc = redis.Redis(host='localhost', port=6379, db=0, password='123456')
        real_sms_code = rdc.get("sms_%s" % mobile)
        print("redis中存放的短信验证码>>>", real_sms_code)
        if not real_sms_code:
            return Response({'message': "短信验证码不存在或已过期", "code": 400})
        if real_sms_code.decode() != sms_code:
            return Response({"code": 400, "msg": "验证码错误"})
        # agree = request.data.get("agree")
        #验证参数
        if not all([username, password, mobile]):
            return Response({"code":204, "msg":"注册信息不完整！"})
        # if not agree:
        #     return Response({"code":204, 'msg':"未同意用户使用协议"})

        try:
            UsersModel.objects.create(username=username, password=password, mobile=mobile)
            return Response({
                "code": 200,
                "msg": "注册成功"
            })

        except Exception as e:
            return Response({
                "code": 400,
                "msg": "注册失败"
            })


# 用户名登录
class LoginView(APIView):
    def post(self,request):
        username=request.data.get("username")
        mobile=request.data.get("phone")
        password=request.data.get("password")
        sms_code = request.data.get("sms_code")
        # 判断短信验证码是否正确
        rdc=redis.Redis(host='localhost',port=6379,db=0,password='123456')
        real_sms_code=rdc.get("sms_%s" % mobile)
        print("redis中存放的短信验证码>>>",real_sms_code)
        if not real_sms_code:
            return Response({'message': "短信验证码不存在或已过期", "code": 400})
        if real_sms_code.decode() != sms_code:
            return Response({"code":400,"msg":"验证码错误"})
        try:
            user=UsersModel.objects.get(username=username)
            # 若不是第一次登陆
            if check_password(password, user.password):
                payload = {
                    "user": user.username
                }
                token = jwt_encode_handler(payload)
                print('token>>>',token)
                user.last_login = timezone.now()
                user.save()
                return Response({"code": 200, "msg": "登陆成功", "data": {"user": user.username, "token": token}})
            else:
                return Response({"code": 403, "msg": "密码错误"})
        except Exception as e:
            print(username,mobile,make_password(password))
            try:
                user_info=UsersModel.objects.create(username=username,phone=mobile,password=make_password(password))

                payload = {
                    "user":user_info.username
                }
                token = jwt_encode_handler(payload)
                print("token>>>",token)
                return Response({
                    "code": 201,
                    "msg": "登陆成功",
                    "data": {"user": user_info.username, "token": token},
                })
            except Exception as e:
                print(e)
                return Response({
                    "code": 500,
                    "msg": "服务端错误"
            })


# 退出登录
class LoginOut(APIView):
    def get(self,request):
        return Response({
            'code':200,
            'msg':'退出成功'
        })